<?php
// +----------------------------------------------------------------------
// | Copyright © Sogu Technologies Co. Ltd 2018-2050 All rights reserved.
// +----------------------------------------------------------------------
// | File name: LoanApplyController.php
// +----------------------------------------------------------------------
// | Author: liuju
// +----------------------------------------------------------------------
// | Description: 描述文档功能
// +----------------------------------------------------------------------
// | Others: 其他内容的说明
// +----------------------------------------------------------------------
// | History: 修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简述
// +----------------------------------------------------------------------
// | 1.Date: 2019-01-05 Author: liuju Modification: 创建
// +----------------------------------------------------------------------

namespace App\Http\Controllers\Frontend\V10\Financial;


use App\Constant\JpushCode;
use App\Constant\QueueKey;
use App\Constant\SmsTemplate;
use App\Constant\NewFlowEnum;
use App\Events\JpushNoticeEvent;
use App\Events\LoanRequestRetryEvent;
use App\Events\NewFlowOrderEvent;
use App\Events\UserLoanApplyEvent;
use App\Exceptions\GeneralException;
use App\Facades\CommonPlatformRequestFacade;
use App\Facades\MoneyPlatformRequestFacade;
use App\Http\Controllers\Controller;
use App\Http\Middleware\CheckCanLoan;
use App\Http\Requests\Frontend\V10\Loan\ApplyLoanRequest;
use App\Jobs\GetLoanResultJobQueue;
use App\Jobs\LoanApplyLoanJionJob;
use App\Models\AdminBankIcon;
use App\Models\LoanApply;
use App\Models\SettingRepayRate;
use App\Models\User;
use App\Models\UserBankCard;
use App\Models\UserChangeBankCardRecord;
use App\Models\UserGlobal;
use App\Models\UserLoanRequest;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;

class LoanApplyController extends Controller
{


    public function __construct()
    {
        $this->middleware('auth:api');
        $this->middleware(CheckCanLoan::class)->only('applyLoan');
    }

    /**
     * Description: 用户放款申请
     * Author: liuju
     * DateTime: 2019-01-10 16:15
     * @param ApplyLoanRequest $request
     * @return mixed
     * @throws GeneralException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \MathPHP\Exception\BadParameterException
     * @throws \ReflectionException
     */
    //public function applyLoan(ApplyLoanRequest $request)
    public function applyLoan(ApplyLoanRequest $request)
    {

        $user = auth('api')->user();

        //$user = User::where('id',25)->first();


        if (!UserGlobal::where('uid', $user->id)->where('global_status', UserGlobal::STATUS_LOAN_REQUEST_SUCCESS)->value('uid')) {
            return failed('当前用户状态不支持放款申请操作');
        }
        //获取用户最新的一条授信成功id
        $loanRequest = UserLoanRequest::where('user_id', $user->id)
            ->where('status', UserLoanRequest::STATUS_SUCCESS)
            ->where('current', UserLoanRequest::CURRENT_NOW)
            ->select('id', 'user_id', 'channel', 'actually_loan_money', 'actually_period', 'credit_id', 'pre_insurance_amt','cash_card_choice_id')
            ->orderByDesc('id')
            ->first();

        if (!$loanRequest) {
            return failed('您尚未完成授信流程，无法执行当前操作');
        }
        if($loanRequest->actually_period >=9){
            return failed('系统处理中请稍后重试');
        }
        // 检测授信数据是否已有放款操作
        $hasLoan = LoanApply::where('loan_request_id',$loanRequest->id)->value('id');
        if($hasLoan){
            return failed('当前授信已有放款申请操作');
        }
        //获取相关费率
        $getReplyRate = SettingRepayRate::getRateByChannl($loanRequest->channel, $loanRequest->actually_period);
        if (!$getReplyRate) {
            Log::debug('手机号为' . $user->phone_num . '的用户于' . date('Y-m-d H:i:s') . '使用Ip地址为' . $request->getClientIp() . '的设备申请放款时，由于setting_replay_rates表中查询channel_code为(' . $loanRequest->channel . ')，period为（' . $loanRequest->actually_period . '）的数据信息不存在导致放款申请操作失败' . PHP_EOL);
            return failed('当前期数不可借款');
        }

        $cardInfo = UserBankCard::find($loanRequest->cash_card_choice_id);
        if(!$cardInfo){
            return failed('未检测到您的收款银行卡，请您选择收款银行卡后重试');
        }
        $cardId = $cardInfo->id;
        Log::debug('JCFC是否有:'.$loanRequest->channel);
        //广大的银行  不用方队列  直接 发起放款  JCFC 晋商 10009 广大

        if ($loanRequest->channel == 'JCFC'){

            //直接入库  然后改放款中状态 is_send_loan = 0
            $ip = $request->getClientIp();
            //$ip = '127.0.0.1';
            $this->JcloanJionJob($user,$loanRequest,$getReplyRate,$cardInfo,$ip);
            return respond([], '正在处理中，请稍后');
        }





        //发起放款申请
        $params = [
            'pre_insurance_amt' => doubleval($loanRequest->pre_insurance_amt / 100),
            'credit_id' => $loanRequest->credit_id,
            'amount' => doubleval($loanRequest->actually_loan_money / 100),
            'period' => $loanRequest->actually_period,
        ];
        $res = MoneyPlatformRequestFacade::applyLoan($params);
        Log::debug('「 用户id为' . $user->id . '使用授信id为' . $loanRequest->credit_id . '银行卡id为' . $cardId . '进行放款申请时。资方放款返回值 」' . json_encode($res, JSON_UNESCAPED_UNICODE));
        if (empty($res) || empty($res['code'])) {
            return failed('请求失败，请重试');
        }
        if ($res['code'] !== '01') {
            return failed('申请放款失败，' . $res['message']);
        }
        $apply = new LoanApply();
        $apply->ip = $request->ip();
        $apply->loan_request_id = $loanRequest->id; //授信id
        $apply->user_id = $user->id;
        $apply->pre_insurance_amt = doubleval($loanRequest->pre_insurance_amt / 100);  //授信额度的前置险
        $apply->trans_money_list = '';  //分账明细
        $apply->bank_card_id = $cardId;  //申请放款的银行卡
        $apply->out_trade_id = !empty($res['data']['outTradeId']) ? $res['data']['outTradeId'] : '';
        $apply->amount = doubleval($loanRequest->actually_loan_money / 100);  //授信表中 申请的借款金额（未扣除前置险）
        $apply->period = $loanRequest->actually_period; //授信表中 申请的分期期限
        $apply->loan_sign = !empty($res['sign']) ? $res['sign'] : '';
        $apply->message = !empty($res['message']) ? $res['message'] : ''; //返回的信息
        $status = !empty($res['data']['status']) ? $res['data']['status'] : $res['subCode'];
        if (!$status) {
            Log::debug('手机号为' . $user->phone_num . '的用户于' . date('Y-m-d H:i:s') . '使用Ip地址为' . $request->getClientIp() . '的设备申请放款时，对user_loan_requests表中id为' . $loanRequest->id . '的记录，向资方申请放款时资方响应信息中subcode字段和data.status字段都不存在导致此次放款申请操作失败' . PHP_EOL);
            return failed('申请放款失败，数据异常');
        }
        $apply->sub_code = $status;
        $apply->loan_status = LoanApply::getLoanStatusByRes($res);
        //费率配置

        foreach ($getReplyRate as $key => $value) {
            if(in_array($key,LoanApply::RATE_KEY)){
                $apply->$key = $value;
            }

        }
        $data = !empty($res['data']) ? $res['data'] : [];
        //新流订单id,还款时使用
        if (!empty($data['loanId'])) {
            $apply->loan_id = $data['loanId'];
        }
        //资方返回的分期数
        if (!empty($data['period'])) {
            $apply->period = $data['period'];
        }
        //资方放款的申请金额
        if (!empty($data['amount'])) {
            $apply->amount = $data['amount'];
        }

        if (!empty($data['loanTime'])) {
            $apply->loan_time = $data['loanTime'];
        }
        //资方返回的明细
        if (!empty($data['transMoneyList'])) {
            $apply->trans_money_list = $data['transMoneyList'];
            //获取放款明细详情
            $detail = LoanApply::getDetailByTransMoneyList($data['transMoneyList']);
            if ($detail['arrival_account']) {
                $apply->arrival_account = $detail['arrival_account'];
            }
            if ($detail['pre_insurance_amt']) {
                $apply->pre_insurance_amt = $detail['pre_insurance_amt'];
            }
            if ($detail['performance_insurance']) {
                $apply->performance_insurance = $detail['performance_insurance'];
            }
        }
        try {
            $apply->save();
        } catch (\Exception $e) {
            Log::debug('「申请放款时」由于' . $e->getMessage() . '错误导致放款结果异常');
            return failed('申请放款异常');
        }
        event(new UserLoanApplyEvent($apply));
        if ($apply->loan_status == LoanApply::LOAN_STATUS_PROCESSING || $apply->loan_status == LoanApply::LOAN_RETRY_APPLY) {
            //任务三分钟后加入队列处理，获取放款处理结果
            // 99 置为放款中
            GetLoanResultJobQueue::dispatch($apply)->onQueue(QueueKey::QUEUE_GET_LOAN_RESULT)->delay(Carbon::now()->addMinutes(3));
        }
        //短信推送
        if ($user->valid && SmsTemplate::TEMPLATE_CONFIRM_LOAN_APPLY_SUCCESS) {
            SmsTemplate::send(SmsTemplate::TEMPLATE_CONFIRM_LOAN_APPLY_SUCCESS, $user->phone_num, ['name' => $user->valid->name]);
        }
        //app消息推送
        if (!empty($user->globalStatus) && $user->globalStatus->jpush_registration_id) {
            event(new JpushNoticeEvent([
                'title' => '要款成功提醒',
                'body' => sprintf('您的%s期%s元借款已完成要款操作，请留意款项到账情况。', $loanRequest->actually_period, intval($loanRequest->actually_loan_money / 100)),
                'audience' => JpushCode::AUDIENCE_TYPE_TWO,
                'to' => [$user->globalStatus->jpush_registration_id],
                'extras' => [
                    'jump_type' => 2,
                ],
            ]));
        }
        event(new NewFlowOrderEvent(NewFlowEnum::NewFlowGetMoney, false ,$loanRequest->id, []));

        return respond([], $res['message']);
    }

    /**
     * Description: 筛选晋商的放款  进行入库  该状态  is_send_loan = 0
     * Author: szg
     * DateTime: 2019-04-03 09:20
     * @return mixed
     * @throws \App\Exceptions\GeneralException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */

    public function JcloanJionJob($user,$loanRequest,$getReplyRate,$cardInfo,$ip)
    {

        $cardId = $cardInfo->id;
        $apply = new LoanApply();
        $apply->ip = $ip;
        $apply->loan_request_id = $loanRequest->id; //授信id
        $apply->user_id = $user->id;
        $apply->pre_insurance_amt = doubleval($loanRequest->pre_insurance_amt / 100);  //授信额度的前置险
        $apply->trans_money_list = '';  //分账明细
        $apply->bank_card_id = $cardId;  //申请放款的银行卡
        $apply->out_trade_id = '';      //资方返回的 合作方借款id
        $apply->amount = doubleval($loanRequest->actually_loan_money / 100);  //授信表中 申请的借款金额（未扣除前置险）
        $apply->period = $loanRequest->actually_period; //授信表中 申请的分期期限
        $apply->loan_sign = ''; //对应新流返回的签名sign，异常时可做校验请求数据用
        $apply->message = ''; //资方返回信息
        //$status = '';

        $apply->loan_status = 1; //通过资方返回的json数组判断处理状态 此处 制为 1 处理中
        try {
            $apply->save();
            //改为正在放款中
            UserGlobal::where(['uid'=>$user->id])->update([
                'global_status' => UserGlobal::STATUS_LOAN_MONEY_PROCESSING,
            ]);
        } catch (\Exception $e) {
            Log::debug('「JCFC进行入库时」由于' . $e->getMessage() . '错误导致入库结果异常');
            return failed('申请放款异常');
        }

    }


    /**
     * Description: 获取放款非成功状态
     * Author: liuju
     * DateTime: 2019-01-13 17:36
     * @return mixed
     * @throws \App\Exceptions\GeneralException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function loanStatus()
    {
        $user = auth('api')->user();
        $userGlobal = UserGlobal::where('uid', $user->id)->first(['global_status']);
        $statusArr = [
            UserGlobal::STATUS_LOAN_MONEY_PROCESSING,
            UserGlobal::STATUS_LOAN_MONEY_FAIL,
            UserGlobal::STATUS_LOAN_CHANGE_CARD,
        ];
        if (!$userGlobal || !in_array($userGlobal->global_status, $statusArr)) {
            return failed('您并无属于此类型状态请求');
        }

        $columns = [
            'loan_apply.amount',
            'loan_apply.period',
            'loan_apply.bank_card_id',
            'user_loan_requests.channel',
            'user_bank_cards.bank_name_show',
            'user_bank_cards.bank_name',
            'user_bank_cards.card_num as bank_card_num',
        ];
        $loanStatusArr = [
            LoanApply::LOAN_CHANGE_CARD,
            LoanApply::LOAN_HANDLE_CHANGE_CARD_FAIL,
            LoanApply::LOAN_STATUS_FAIL,
            LoanApply::LOAN_STATUS_PROCESSING,
            LoanApply::LOAN_CHANGE_CARD_HANDLING
        ];
        $data = LoanApply::leftJoin('user_loan_requests', 'user_loan_requests.id', 'loan_apply.loan_request_id')
            ->leftJoin('user_bank_cards', 'user_bank_cards.id', 'loan_apply.bank_card_id')
            ->where('loan_apply.user_id', $user->id)
            ->whereIn('loan_apply.loan_status', $loanStatusArr)
            ->orderByDesc('loan_apply.id')
            ->first($columns);
        if(!$data){
            return failed('您并不存在需要放款的数据');
        }
        $data = $data->toArray();
        $data['bank_card_num'] = mb_substr($data['bank_card_num'], -4);
        $data['bank_icon'] = AdminBankIcon::where('bank_name',$data['bank_name'])
            ->orWhere('bank_name',$data['bank_name_show'])
            ->value('icon_oss_url');
        if (!$data['bank_icon']) {
           $other = AdminBankIcon::where('bank_name', '其他')->value('icon_oss_url');
           if($other){
               $data['bank_icon'] = Storage::disk('oss')->signUrl($other);
           }else{
               $data['bank_icon'] = '';
           }
        }else{
            $data['bank_icon'] = Storage::disk('oss')->signUrl($data['bank_icon']);
        }
        unset($data['bank_name']);
        $params = [
            'applyAmount' => $data['amount'],
            'period' => $data['period'],
            'channel' => $data['channel'],
        ];
        unset($data['channel']);
        $data['bank_card_info'] = sprintf('%s(%s)', $data['bank_name_show'], $data['bank_card_num']);
        unset($data['bank_name_show']);
        unset($data['bank_card_num']);
        //计算分期
        $periodDetail = UserLoanRequest::getCalculate($params);
        $data['period_money'] = $periodDetail['total_amount'];
        return success($data, [], '请求成功');
    }


    /**
     * Description: 用户放款失败确认
     * Author: liuju
     * DateTime: 2019-01-13 22:25
     * @return mixed
     * @throws GeneralException
     */
    public function failConfirm()
    {
        try {
            $user = auth('api')->user();
            $userGlobal = UserGlobal::where('uid', $user->id)
                ->where('global_status', UserGlobal::STATUS_LOAN_MONEY_FAIL)
                ->value('uid');
            if (!$userGlobal) {
                return failed('该用户不可进行当前操作');
            }
            UserGlobal::where('uid', $user->id)->update([
                'global_status' => UserGlobal::STATUS_NOTHING,
                'last_request_fail_time' => date('Y-m-d'),
            ]);
            return success([], [], '确认成功');
        } catch (\Exception $e) {
            throw  new GeneralException($e->getMessage());
        }
    }
}